#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QPicture>
#include <QDateTime>
#include <QMessageBox>
#include <QFileDialog>

#include <cstdio>
#include <iostream>
#include <fstream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // DEBUG - Default values for debugging
    _Network1Name = "eth0";
    _Network2Name = "none";

    for(int i = 0; i < 4; i++){
        _Network1IPAddress[i] = 0;
        _Network2IPAddress[i] = 0;
    }

    // Variable initialization
    _network1CheckIsStillRunning = false;
    _network2CheckIsStillRunning = false;
    _internetCheckIsStillRunning = false;
    _VICONcheckIsStillRunning = false;
    _ArduinocheckIsStillRunning = false;

    _Network1IsConnected = false;
    _Network2IsConnected = false;
    _InternetIsConnected = false;
    _VICONIsConnected = false;
    _VICONCanBePinged = false;
    _ArduinoIsConnected = false;
    _ArduinoCanBePinged = false;

    // Set up UI elements with values
    ui->edit_fileLogLocation->setText(_GCSObject.GetFileLogLocation());
    UpdateLogList();

    // Set up the AH
    AH_Core = new AHclass;
    AH_Core->show();
    ui->scroll_AH->setWidget(AH_Core);

    // Set up signals and slots
    // Connect the GUI to the debug network test object methods
    connect(this, SIGNAL(DEBUG_Do_runPingTest(int*)), &DEBUG_NetworkTests, SLOT(runPingTest(int*)));
    connect(this, SIGNAL(DEBUG_Do_runNetworkInterfaceTest(QString)), &DEBUG_NetworkTests, SLOT(runNetworkInterfaceTest(QString)));

    // Connects the GUI to the signals sent from the NetworkTestThread used for debugging
    connect(&DEBUG_NetworkTests, SIGNAL(pingTestCompleted(float)), this, SLOT(DEBUG_pingResult(float)));
    connect(&DEBUG_NetworkTests, SIGNAL(networkInterfaceTestCompleted(int*)), this, SLOT(DEBUG_interfaceTestResult(int*)));
    connect(&DEBUG_NetworkTests, SIGNAL(DEBUG_NetworkTestsMessage(QString)), this, SLOT(DEBUG_debugMessage(QString)));

    // Connects the GUI to the GCS, for notifications when a new log file is created
    connect(&_GCSObject, SIGNAL(newLogFileCreated()), this, SLOT(UpdateLogList()));

    // Connects the GUI to the AeroQuad object within the GCS
    connect(this, SIGNAL(Do_AeroQuad_ChangeIP(int*)), &(_GCSObject._aeroQuadModel), SLOT(changeIPAddress(int*)));
    connect(&(_GCSObject._aeroQuadModel), SIGNAL(ipAddressHasBeenChanged()), this, SLOT(RespondAeroQuadIPAddressChanged()));

    // Connects the GUI to the VICON object within the GCS
    connect(this, SIGNAL(Do_VICON_ChangeIP(int*)), &(_GCSObject._VICONModel), SLOT(changeIPAddress(int*)));
    connect(&(_GCSObject._VICONModel), SIGNAL(ipAddressHasBeenChanged()), this, SLOT(RespondVICONIPAddressChanged()));

    // Move all objects to the appropriate threads
    DEBUG_NetworkTests.moveToThread(&DEBUG_NetworkTestsThread);
    _GCSObject.moveToThread(&_GCSThread);

    // Start all the threads
    DEBUG_NetworkTestsThread.start();
    _GCSThread.start();

    // Create, connect and start all timers
    connect(&_AHUpdateTimer, SIGNAL(timeout()), this, SLOT(updateAH()));
    _AHUpdateTimer.start(40);
    updateAH();

    connect(&_liveLogUpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateLiveLog()));
    _liveLogUpdateTimer.start(1000);
    UpdateLiveLog();

    connect(&_numericalDisplayUpdateTimer, SIGNAL(timeout()), this, SLOT(updateNumericalDisplays()));
    _numericalDisplayUpdateTimer.start(40);
    updateNumericalDisplays();

    connect(&_connectionStatusUpdateTimer, SIGNAL(timeout()), this, SLOT(DoConnectionStatusDisplayUpdate()));
    _connectionStatusUpdateTimer.start(1000);
    DoConnectionStatusDisplayUpdate();

    connect(&_network1ConnectionCheckTimer, SIGNAL(timeout()), this, SLOT(DoNetwork1ConnectionCheck()));
    _network1ConnectionCheckTimer.start(1000);
    DoNetwork1ConnectionCheck();

    connect(&_network2ConnectionCheckTimer, SIGNAL(timeout()), this, SLOT(DoNetwork2ConnectionCheck()));
    _network2ConnectionCheckTimer.start(1000);
    DoNetwork2ConnectionCheck();

    connect(&_internetConnectionCheckTimer, SIGNAL(timeout()), this, SLOT(DoInternetConnectionCheck()));
    _internetConnectionCheckTimer.start(10000);
    DoInternetConnectionCheck();

    connect(&_ArduinoConnectionCheckTimer, SIGNAL(timeout()), this, SLOT(DoArduinoConnectionCheck()));
    _ArduinoConnectionCheckTimer.start(10000);
    DoArduinoConnectionCheck();

    connect(&_VICONConnectionCheckTimer, SIGNAL(timeout()), this, SLOT(DoVICONConnectionCheck()));
    _VICONConnectionCheckTimer.start(10000);
    DoVICONConnectionCheck();
}

MainWindow::~MainWindow()
{
    /* Tell threads that the UI is closing, and that it is time for them to
     * end */
    emit UIIsClosing();

    // End timers
    _connectionStatusUpdateTimer.stop();

    // End threads
    DEBUG_NetworkTestsThread.exit();
    _GCSThread.exit();

    delete ui;
}

void MainWindow::on_actionQuit_triggered()
{
    this->close();
}

void MainWindow::on_action_viewLogging_triggered()
{
    ui->alltabs->setCurrentIndex(0);
}

void MainWindow::on_action_viewControlValues_triggered()
{
    ui->alltabs->setCurrentIndex(1);
}

void MainWindow::on_action_viewConnections_triggered()
{
    ui->alltabs->setCurrentIndex(2);
}

void MainWindow::on_action_viewHelp_triggered()
{
    ui->alltabs->setCurrentIndex(3);
}

void MainWindow::on_action_viewDebug_triggered()
{
    ui->alltabs->setCurrentIndex(4);
}

void MainWindow::on_button_DEBUG_Ping_clicked()
{
    int *ipAddress = new int[4];
    *(ipAddress) = 127;
    *(ipAddress + 1) = 0;
    *(ipAddress + 2) = 0;
    *(ipAddress + 3) = 1;

    emit DEBUG_Do_runPingTest(ipAddress);
}

void MainWindow::on_button_DEBUG_Interface_clicked()
{
    emit DEBUG_Do_runNetworkInterfaceTest("eth0");
}

// Custom methods

/*
  DEBUG_pingResult

  Desc - Gets the result of the ping thread. Used for testing.
  */
void MainWindow::DEBUG_pingResult(float pingResult)
{
    QString logOutput;

    logOutput = "Ping Result - ";

    if(pingResult == -1){
        logOutput += "Failure";
    } else {
        logOutput += "Success";
    }

    ui->list_debugLog->addItem(logOutput);
}

/*
  DEBUG_interfaceTestResult

  Desc - Processes the result of a network interface test
  */
void MainWindow::DEBUG_interfaceTestResult(int *ipAddress)
{
    QString logOutput;

    logOutput = "Interface Test Result - ";

    if(*ipAddress == GCSCommon::DoesNotExist){
        logOutput += "Does not exist";
    } else if(*ipAddress == GCSCommon::NoIP){
        logOutput += "No IP";
    } else {
        logOutput += " Has IP: ";
        for(int i = 0; i < 4; i++){
            logOutput += QString::number(*(ipAddress + i));
            logOutput += ".";
        }
        logOutput.chop(1);
    }

    ui->list_debugLog->addItem(logOutput);

    delete ipAddress;
}

/*
  DEBUG_debugMessage

  Desc - Displays a message from any object in the debug log
  */
void MainWindow::DEBUG_debugMessage(QString message)
{
    ui->list_debugLog->addItem(message);
}


/*
  StartArtificialHorizon

  Desc - Sets up and begins the animation of the artificial horizon.
  */
void MainWindow::StartArtificialHorizon()
{

}

/*
  StopArtificialHorizon

  Desc - Stops the animation of the artifical horizon
  */
void MainWindow::StopArtificialHorizon()
{

}

/*
  DoArtificialHorizonUpdate

  Desc - Performs an update of the articial horizon.
         Called by the _AHAnimationTimer
  */
void MainWindow::DoArtificialHorizonUpdate()
{


}


/*
  StartConnectionLoops

  Desc - Sets up and starts the connection check and connection status
         UI update loops, which continually check the
         connection status of each connection
  */
void MainWindow::StartConnectionLoops()
{

}

/*
  StopConnectionLoops

  Desc - Stops all connection related loops
  */
void MainWindow::StopConnectionLoops()
{

}


/*
  DoNetwork1ConnectionCheck

  Desc - Checks the status of the Network connection through a ping test,
         and gets the connection's IP address
  */
void MainWindow::DoNetwork1ConnectionCheck()
{
    if(!_network1CheckIsStillRunning){
        _network1CheckIsStillRunning = true;

        connect(this, SIGNAL(Do_Network1_runNetworkInterfaceTest(QString)), &_network1Tests, SLOT(runNetworkInterfaceTest(QString)));
        connect(&_network1Tests, SIGNAL(networkInterfaceTestCompleted(int*)), this, SLOT(ProcessNetwork1ConnectionCheck(int*)));
        _network1Tests.moveToThread(&_network1TestThread);
        _network1TestThread.start();

        emit Do_Network1_runNetworkInterfaceTest(_Network1Name);
    }
}

/*
  DoNetwork2ConnectionCheck

  Desc - Checks the status of the Network connection through a ping test,
         and gets the connection's IP address
  */
void MainWindow::DoNetwork2ConnectionCheck()
{
    if(!_network2CheckIsStillRunning){
        _network2CheckIsStillRunning = true;

        connect(this, SIGNAL(Do_Network2_runNetworkInterfaceTest(QString)), &_network2Tests, SLOT(runNetworkInterfaceTest(QString)));
        connect(&_network2Tests, SIGNAL(networkInterfaceTestCompleted(int*)), this, SLOT(ProcessNetwork2ConnectionCheck(int*)));
        _network2Tests.moveToThread(&_network2TestThread);
        _network2TestThread.start();

        emit Do_Network2_runNetworkInterfaceTest(_Network2Name);
    }
}

/*
  DoInternetConnectionCheck

  Desc - Checks the status of the Internet connection through a ping test,
         and gets the connection's IP address
  */
void MainWindow::DoInternetConnectionCheck()
{
    if(!_internetCheckIsStillRunning){
        _internetCheckIsStillRunning = true;

        int *ipAddress = new int[4];

        connect(this, SIGNAL(Do_Internet_runDNSTest()), &_internetTests, SLOT(runDNSTest()));
        connect(&_internetTests, SIGNAL(DNSTestCompleted(bool)), this, SLOT(ProcessInternetConnectionCheck(bool)));
        _internetTests.moveToThread(&_internetTestThread);
        _internetTestThread.start();

        emit Do_Internet_runDNSTest();
    }
}

/*
  DoVICONConnectionCheck

  Desc - Checks the status of the VICON connection through a ping test,
         and gets the connection's IP address
  */
void MainWindow::DoVICONConnectionCheck()
{
    if(!_VICONcheckIsStillRunning){
        _VICONcheckIsStillRunning = true;

        connect(this, SIGNAL(Do_VICON_runPingTest(int*)), &_VICONTests, SLOT(runPingTest(int*)));
        connect(&_VICONTests, SIGNAL(pingTestCompleted(float)), this, SLOT(ProcessVICONConnectionCheck(float)));
        _VICONTests.moveToThread(&_VICONTestThread);
        _VICONTestThread.start();

        emit Do_VICON_runPingTest(_GCSObject._VICONModel.getIPAddress());
    }
}

/*
  DoAeroQuadConnectionCheck

  Desc - Checks the status of the AeroQuad connection through
         a ping test, and gets the connection's IP address
  */
void MainWindow::DoArduinoConnectionCheck()
{
    if(!_ArduinocheckIsStillRunning){
        _ArduinocheckIsStillRunning = true;

        connect(this, SIGNAL(Do_Arduino_runPingTest(int*)), &_arduinoTests, SLOT(runPingTest(int*)));
        connect(&_arduinoTests, SIGNAL(pingTestCompleted(float)), this, SLOT(ProcessArduinoConnectionCheck(float)));
        _arduinoTests.moveToThread(&_arduinoTestThread);
        _arduinoTestThread.start();

        emit Do_Arduino_runPingTest(_GCSObject._aeroQuadModel.getIPAddress());
    }
}

/*
  DoConnectionStatusDisplayUpdate

  Desc - Updates the various displays in the UI which show
         connection statues and information
  */
void MainWindow::DoConnectionStatusDisplayUpdate()
{
    QString ipAddressHolder;
    ipAddressHolder = "";

    // Network 1
    ui->label_sidebarNetwork1Name->setText("Network (" + _Network1Name + ")");
    ui->label_tabNetwork1Name->setText("Network (" + _Network1Name + ")");

    if(_Network1IsConnected){
        ui->label_sidebarNetwork1Connected->setText("Connected");
        ui->label_tabNetwork1Connected->setText("Connected");
    } else {
        ui->label_sidebarNetwork1Connected->setText("Not connected");
        ui->label_tabNetwork1Connected->setText("Not connected");
    }

    for(int i = 0; i < 4; i++){
        ipAddressHolder += QString::number(_Network1IPAddress[i]);
        ipAddressHolder += ".";
    }
    ipAddressHolder.chop(1);

    ui->edit_ipNetwork1->setText(ipAddressHolder);

    ipAddressHolder = "";


    // Network 2
    ui->label_sidebarNetwork2Name->setText("Network (" + _Network2Name + ")");
    ui->label_tabNetwork2Name->setText("Network (" + _Network2Name + ")");

    if(_Network2IsConnected){
        ui->label_sidebarNetwork2Connected->setText("Connected");
        ui->label_tabNetwork2Connected->setText("Connected");
    } else {
        ui->label_sidebarNetwork2Connected->setText("Not connected");
        ui->label_tabNetwork2Connected->setText("Not connected");
    }

    for(int i = 0; i < 4; i++){
        ipAddressHolder += QString::number(_Network2IPAddress[i]);
        ipAddressHolder += ".";
    }
    ipAddressHolder.chop(1);

    ui->edit_ipNetwork2->setText(ipAddressHolder);

    ipAddressHolder = "";


    // Internet
    if(_InternetIsConnected){
        ui->label_sidebarInternetConnected->setText("Connected");
        ui->label_tabInternetConnected->setText("Connected");
    } else {
        ui->label_sidebarInternetConnected->setText("Not connected");
        ui->label_tabInternetConnected->setText("Not connected");
    }


    // Arduino
    if(_ArduinoCanBePinged){
        if(_ArduinoIsConnected){
            ui->label_sidebarArduinoConnected->setText("Connected");
            ui->label_tabArduinoConnected->setText("Connected");
        } else {
            ui->label_sidebarArduinoConnected->setText("Ping success");
            ui->label_tabArduinoConnected->setText("Ping success");
        }
    } else {
        ui->label_sidebarArduinoConnected->setText("Not connected");
        ui->label_tabArduinoConnected->setText("Not connected");
    }


    // VICON
    if(_VICONCanBePinged){
        if(_VICONIsConnected){
            ui->label_sidebarVICONConnected->setText("Connected");
            ui->label_tabVICONConnected->setText("Connected");
        } else {
            ui->label_sidebarVICONConnected->setText("Ping success");
            ui->label_tabVICONConnected->setText("Ping success");
        }
    } else {
        ui->label_sidebarVICONConnected->setText("Not connected");
        ui->label_tabVICONConnected->setText("Not connected");
    }


    // Device Connections diagram
    //
    // Invovles working out which combinations of connections are connected
    if(!(_Network1IsConnected || _Network2IsConnected)){
        ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_a.png"));
    } else {
        ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_b.png"));
        if(_ArduinoIsConnected){
            ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_c.png"));

            if(_InternetIsConnected){
                ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_d.png"));

                if(_VICONIsConnected){
                    ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_e.png"));

                }
            }
        } else {
            if(_InternetIsConnected){
                ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_f.png"));

                if(_VICONIsConnected){
                    ui->label_connDiagram->setPixmap(QPixmap(":/images/fbd_g.png"));

                }
            }
        }
    }
}

void MainWindow::ProcessNetwork1ConnectionCheck(int *ipAddress)
{
    // Check to see if the test was successful
    if((*(ipAddress) == -1) || (*(ipAddress) == -2)){
        _Network1IsConnected = false;

        for(int i = 0; i < 4; i++){
            _Network1IPAddress[i] = 0;
        }
    } else {
        _Network1IsConnected = true;

        for(int i = 0; i < 4; i++){
            _Network1IPAddress[i] = *(ipAddress + i);
        }
    }

    delete ipAddress;

    disconnect(&_network1Tests, SIGNAL(networkInterfaceTestCompleted(int*)), this, SLOT(ProcessNetwork1ConnectionCheck(int*)));
    disconnect(this, SIGNAL(Do_Network1_runNetworkInterfaceTest(QString)), &_network1Tests, SLOT(runNetworkInterfaceTest(QString)));

    _network1TestThread.exit();

    _network1CheckIsStillRunning = false;
}

void MainWindow::ProcessNetwork2ConnectionCheck(int *ipAddress)
{
    // Check to see if the test was successful
    if((*(ipAddress) == -1) || (*(ipAddress) == -2)){
        _Network2IsConnected = false;

        for(int i = 0; i < 4; i++){
            _Network2IPAddress[i] = 0;
        }
    } else {
        _Network2IsConnected = true;

        for(int i = 0; i < 4; i++){
            _Network2IPAddress[i] = *(ipAddress + i);
        }
    }

    delete ipAddress;

    disconnect(&_network2Tests, SIGNAL(networkInterfaceTestCompleted(int*)), this, SLOT(ProcessNetwork2ConnectionCheck(int*)));
    disconnect(this, SIGNAL(Do_Network2_runNetworkInterfaceTest(QString)), &_network2Tests, SLOT(runNetworkInterfaceTest(QString)));

    _network2TestThread.exit();

    _network2CheckIsStillRunning = false;
}

void MainWindow::ProcessInternetConnectionCheck(bool testPassed)
{
    _InternetIsConnected = testPassed;

    disconnect(this, SIGNAL(Do_Internet_runDNSTest()), &_internetTests, SLOT(runDNSTest()));
    disconnect(&_internetTests, SIGNAL(DNSTestCompleted(bool)), this, SLOT(ProcessInternetConnectionCheck(bool)));

    _internetTestThread.exit();

    _internetCheckIsStillRunning = false;
}

void MainWindow::ProcessArduinoConnectionCheck(float pingResult)
{
    if(pingResult > 0){
        _ArduinoCanBePinged = true;
    } else {
        _ArduinoCanBePinged = false;
    }

    _arduinoTestThread.exit();

    disconnect(this, SIGNAL(Do_Arduino_runPingTest(int*)), &_arduinoTests, SLOT(runPingTest(int*)));
    disconnect(&_arduinoTests, SIGNAL(pingTestCompleted(float)), this, SLOT(ProcessArduinoConnectionCheck(float)));

    _ArduinocheckIsStillRunning = false;
}

void MainWindow::ProcessVICONConnectionCheck(float pingResult)
{
    _VICONTestThread.exit();

    if(pingResult > 0){
        _VICONCanBePinged = true;
    } else {
        _VICONCanBePinged = false;
    }

    disconnect(this, SIGNAL(Do_VICON_runPingTest(int*)), &_VICONTests, SLOT(runPingTest(int*)));
    disconnect(&_VICONTests, SIGNAL(pingTestCompleted(float)), this, SLOT(ProcessVICONConnectionCheck(float)));

    _VICONcheckIsStillRunning = false;
}

void MainWindow::updateAH()
{
    AH_Core->setState(_GCSObject._aeroQuadModel.getRoll(), _GCSObject._aeroQuadModel.getPitch(),
                      _GCSObject._aeroQuadModel.getRollRate(), _GCSObject._aeroQuadModel.getPitchRate());
}


/*
  LoadSettingsFromFile

  Desc - Loads all settings from the settings file
  */
void MainWindow::LoadSettingsFromFile()
{

}

/*
  SaveSettingsToFile

  Desc - Saves all settings to the settings file
  */
void MainWindow::SaveSettingsToFile()
{

}


/*
  ChangeLiveLogUpdateFrequency

  Desc - Changes the rate at which the live log is updated.
         Stops the live log timer, and restarts it with the
         passed update rate value (in ms)
  */
void MainWindow::ChangeLiveLogUpdateFrequency(int updateRate)
{
    _liveLogUpdateTimer.stop();

    _liveLogUpdateTimer.start(updateRate);
}

/*
  UpdateLiveLog

  Desc - Writes to the live log. Called by the live log update timer.
  */
void MainWindow::UpdateLiveLog()
{
    QString newRow = "";

    newRow = QDateTime::currentDateTime().toLocalTime().toString();
    newRow += " - ";
    newRow += _GCSObject._aeroQuadModel.toLiveLogEntry();

    ui->list_liveLog->insertItem(0, newRow);

    newRow = _GCSObject._aeroQuadModel.toRollLiveLogEntry();
    ui->list_rollLog->insertItem(0, newRow);

    newRow = _GCSObject._aeroQuadModel.toPitchLiveLogEntry();
    ui->list_pitchLog->insertItem(0, newRow);

    newRow = _GCSObject._aeroQuadModel.toYawLiveLogEntry();
    ui->list_yawLog->insertItem(0, newRow);
}

/*
  UpdateLogList

  Desc - Looks at the location where log files are stored, and looks for
                 OSIQ GCS log files. Puts the names of all these files into the log file list
  */
void MainWindow::UpdateLogList()
{
    QDir currentLogLocation(_GCSObject.GetFileLogLocation());

    // Ref - http://developer.qt.nokia.com/doc/qt-4.7/qdir.html#id-ee60b13e-a1ba-4c20-9f25-0746fd32457f
    QString fileName;
    QStringList filters, fileList;
    filters << "OSIQLog_*";
    currentLogLocation.setNameFilters(filters);

    fileList = currentLogLocation.entryList();

    ui->list_fileLogList->clear();

    foreach(fileName, fileList){
        fileName.chop(4);
        // NOTE - 8 is the length of the log file name prefix, "OSIQLog_"
        fileName = fileName.right(fileName.length() - 8);

        ui->list_fileLogList->insertItem(0, fileName);
    }
}


/*
  ResetRollGainValues

  Desc - Gets roll gains from the settings files and puts them
         in the low and high boxes and locks the ranges
  */
void MainWindow::ResetRollGainValues()
{

}

/*
  ResetPitchGainValues

  Desc - Gets pitch gains from the settings files and puts them
         in the low and high boxes and locks the ranges
  */
void MainWindow::ResetPitchGainValues()
{

}

/*
  ResetYawGainValues

  Desc - Gets yaw gains from the settings files and puts them in
         the low and high boxes and locks the ranges
  */
void MainWindow::ResetYawGainValues()
{

}


/*
  SaveGainValues

  Desc - Saves gain values in the UI to the settings file
  */
void MainWindow::SaveGainValues()
{

}

void MainWindow::on_button_changeIPVICON_clicked()
{
    int *newIPAddress;

    // Disable the entry of a new IP address until the IP address has been changed
    ui->button_changeIPVICON->setEnabled(false);
    ui->spin_ipVICON_1->setEnabled(false);
    ui->spin_ipVICON_2->setEnabled(false);
    ui->spin_ipVICON_3->setEnabled(false);
    ui->spin_ipVICON_4->setEnabled(false);

    // If control reaches here, the ip address entered is valid
    // Turn the IP address into an int array
    newIPAddress = new int[4];

    *(newIPAddress) = ui->spin_ipVICON_1->value();
    *(newIPAddress + 1) = ui->spin_ipVICON_2->value();
    *(newIPAddress + 2) = ui->spin_ipVICON_3->value();
    *(newIPAddress + 3) = ui->spin_ipVICON_4->value();

    // Tell the GCS to change the IP of the VICON
    emit Do_VICON_ChangeIP(newIPAddress);
}

void MainWindow::on_button_changeIPArduino_clicked()
{
    int *newIPAddress;

    // Disable the entry of a new IP address until the IP address has been changed
    ui->button_changeIPArduino->setEnabled(false);
    ui->spin_ipArduino_1->setEnabled(false);
    ui->spin_ipArduino_2->setEnabled(false);
    ui->spin_ipArduino_3->setEnabled(false);
    ui->spin_ipArduino_4->setEnabled(false);

    // Turn the IP address into an int array
    newIPAddress = new int[4];

    *(newIPAddress) = ui->spin_ipArduino_1->value();
    *(newIPAddress + 1) = ui->spin_ipArduino_2->value();
    *(newIPAddress + 2) = ui->spin_ipArduino_3->value();
    *(newIPAddress + 3) = ui->spin_ipArduino_4->value();

    // Tell the GCS to change the IP of the Arduino/AeroQuad
    emit Do_AeroQuad_ChangeIP(newIPAddress);
}

void MainWindow::RespondAeroQuadIPAddressChanged()
{
    ui->button_changeIPArduino->setEnabled(true);
    ui->spin_ipArduino_1->setEnabled(true);
    ui->spin_ipArduino_2->setEnabled(true);
    ui->spin_ipArduino_3->setEnabled(true);
    ui->spin_ipArduino_4->setEnabled(true);
}

void MainWindow::RespondVICONIPAddressChanged()
{
    ui->button_changeIPVICON->setEnabled(true);
    ui->spin_ipVICON_1->setEnabled(true);
    ui->spin_ipVICON_2->setEnabled(true);
    ui->spin_ipVICON_3->setEnabled(true);
    ui->spin_ipVICON_4->setEnabled(true);
}

void MainWindow::on_slide_sampleFreq_sliderMoved(int position)
{
    ui->spin_sampleFreq->setValue(position);

    ChangeLiveLogUpdateFrequency(position);
}

void MainWindow::on_spin_sampleFreq_valueChanged(int value)
{
    ui->slide_sampleFreq->setValue(value);

    ChangeLiveLogUpdateFrequency(value);
}

void MainWindow::on_button_toggleFileLogging_clicked()
{
    ToggleFileLogging();
}

void MainWindow::on_actionToggle_File_Logging_triggered()
{
    ToggleFileLogging();
}

void MainWindow::ToggleFileLogging()
{
    _GCSObject.toggleFileLogging();

    if(_GCSObject.isFileLoggingRunning())
    {
        //Yes, it is (true)
        ui->button_toggleFileLogging->setText("Stop");
        ui->actionToggle_File_Logging->setText("Stop File Logging");

    } else {
        //No, it isn't (false)
        ui->button_toggleFileLogging->setText("Start");
        ui->actionToggle_File_Logging->setText("Start File Logging");
    }
}

void MainWindow::on_button_changeFileLogSaveLocation_clicked()
{
    bool prevIsFileLoggingValue;
    QString newSaveLocation = "";

    prevIsFileLoggingValue = _GCSObject.isFileLoggingRunning();

    if(prevIsFileLoggingValue){
        _GCSObject.toggleFileLogging();
    }

    // Get a new directory
    newSaveLocation = QFileDialog::getExistingDirectory(this, "Please select a location to save log files", "~/");

    _GCSObject.SetFileLogLocation(newSaveLocation);

    ui->edit_fileLogLocation->setText(_GCSObject.GetFileLogLocation());

    UpdateLogList();

   if(prevIsFileLoggingValue){
        _GCSObject.toggleFileLogging();
   }
}

void MainWindow::on_list_fileLogList_doubleClicked(QModelIndex index)
{
    QString fileName, fileLocation;
    FILE *stream;

    // Reconstruct the name of the file double clicked
    fileName = ui->list_fileLogList->item(index.row())->text();
    fileName = "OSIQLog_" + fileName + ".csv";

    fileLocation = "gedit \"" + _GCSObject.GetFileLogLocation() + "/" + fileName + "\"";

    stream = popen(fileLocation.toStdString().c_str(), "r");
    pclose(stream);
}

void MainWindow::on_button_DEBUG_AH_clicked()
{
    AH_Core->setState(30,30,0,0);
}

void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
    _GCSObject._aeroQuadModel.processData(QString::number(ui->horizontalSlider->value()) + "," + QString::number(ui->horizontalSlider_2->value()));
}

void MainWindow::on_horizontalSlider_2_sliderMoved(int position)
{
    _GCSObject._aeroQuadModel.processData(QString::number(ui->horizontalSlider->value()) + "," + QString::number(ui->horizontalSlider_2->value()));
}

void MainWindow::updateNumericalDisplays()
{
    ui->lcd_Roll->display(_GCSObject._aeroQuadModel.getRoll());
    ui->lcd_Pitch->display(_GCSObject._aeroQuadModel.getPitch());
    ui->lcd_Yaw->display(_GCSObject._aeroQuadModel.getYaw());

    ui->lcd_RollRate->display(_GCSObject._aeroQuadModel.getRollRate());
    ui->lcd_PitchRate->display(_GCSObject._aeroQuadModel.getPitchRate());
    ui->lcd_YawRate->display(_GCSObject._aeroQuadModel.getYawRate());

    ui->lcd_X->display(_GCSObject._aeroQuadModel.getXPosition());
    ui->lcd_Y->display(_GCSObject._aeroQuadModel.getYPosition());
    ui->lcd_Z->display(_GCSObject._aeroQuadModel.getZPosition());

    ui->lcd_XVelocity->display(_GCSObject._aeroQuadModel.getXVelocity());
    ui->lcd_YVelocity->display(_GCSObject._aeroQuadModel.getYVelocity());
    ui->lcd_ZVelocity->display(_GCSObject._aeroQuadModel.getZVelocity());
}
